using Autofac;
using Hangfire;
using Hangfire.Dashboard.BasicAuthorization;
using Hangfire.MySql;
using HangfireTask;
using Microsoft.OpenApi.Models;
using Model.Domain;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System.Reflection;
using System.Transactions;
using Utils;

namespace TaskManager
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddSqlsugarSetup(Configuration);
            services.AddSingleton(new AppSettings(Configuration));
            services.AddHttpContextAccessor();

            var hangfireConnectionString = Configuration.GetConnectionString("hangFire");
            services.AddHangfire(configuration => configuration
         .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
         .UseSimpleAssemblyNameTypeSerializer()
         .UseRecommendedSerializerSettings()
         .UseStorage(new MySqlStorage(
             hangfireConnectionString,
             new MySqlStorageOptions
             {
                 TransactionIsolationLevel = IsolationLevel.ReadCommitted,
                 QueuePollInterval = TimeSpan.FromSeconds(15),
                 JobExpirationCheckInterval = TimeSpan.FromHours(1),
                 CountersAggregateInterval = TimeSpan.FromMinutes(5),
                 PrepareSchemaIfNecessary = true,
                 DashboardJobListLimit = 50000,
                 TransactionTimeout = TimeSpan.FromMinutes(1),
                 TablesPrefix = "Hangfire"
             })
         ));

            services.AddHangfireServer();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "TaskManager", Version = "v1" });
            });

            //services.Configure<List<Tenant>>(Configuration.GetSection("Tenants"));
            services.Configure<List<MutiDBOperate>>(Configuration.GetSection("DBS"));
            services.Configure<RedisCon>(Configuration.GetSection("RedisCon"));
            //services.Configure<AlimtConfig>(Configuration.GetSection("AlimtConfig"));
        }
               
        public void ConfigureContainer(ContainerBuilder _Builder)
        {
            var iService = Assembly.Load("IService");
            var rService = Assembly.Load("Service");

            _Builder.RegisterAssemblyTypes(iService, rService).Where(i => i.Name.EndsWith("Service")).AsImplementedInterfaces();
        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TaskManager v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            //HangFire
            var filter = new BasicAuthAuthorizationFilter(
                new BasicAuthAuthorizationFilterOptions
                {
                    SslRedirect = false,
                    // Require secure connection for dashboard
                    RequireSsl = false,
                    // Case sensitive login checking
                    LoginCaseSensitive = false,
                    // Users
                    Users =
                    [
                        new BasicAuthAuthorizationUser
                        {
                            Login = "hangfire",
                            PasswordClear = "hangfire"
                        }
                    ]
                });
            var options = new DashboardOptions
            {
                AppPath = "/",//返回时跳转的地址
                DisplayStorageConnectionString = false,// 是否显示数据库连接信息
                Authorization = [
                    filter
                ],
                IsReadOnlyFunc = Context =>
                {
                    return false;//是否只读面板
                }
            };
            app.UseHangfireDashboard("/task/job", options);
            HangfireDispose.HangfireService();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

    public static class SqlsugarSetup
    {
        public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration)
        {
            List<MutiDBOperate> listdatabase = new();

            string Path = "appsettings.json";
            using (var file = new StreamReader(Path))
            using (var reader = new JsonTextReader(file))
            {
                var jObj = (JObject)JToken.ReadFrom(reader);
                if (!string.IsNullOrWhiteSpace("DBS"))
                {
                    var secJt = jObj["DBS"];
                    if (secJt != null)
                    {
                        for (int i = 0; i < secJt.Count(); i++)
                        {
                            if (bool.Parse(secJt[i]["Enabled"].ToString()))
                            {
                                listdatabase.Add(new MutiDBOperate()
                                {
                                    ConnId = secJt[i]["ConnId"].ToString(),
                                    Conn = secJt[i]["Connection"].ToString(),
                                    HitRate = Convert.ToInt32(secJt[i]["HitRate"].ToString()),
                                });
                            }
                        }
                    }
                }
            }

            var listConfig = new List<ConnectionConfig>();
            var expMethods = new List<SqlFuncExternal>();
            ICacheService myCache = new SugarCache();
            listdatabase.ForEach(m =>
            {
                listConfig.Add(new ConnectionConfig()
                {
                    ConfigId = m.ConnId,
                    ConnectionString = m.Conn,
                    DbType = DbType.MySql,
                    IsAutoCloseConnection = true,
                    //IsShardSameThread = false, //用SqlSugarScope单例模式取代SqlSugarClient+IsShardSameThread效果一样，并且支持异步，
                    AopEvents = new AopEvents
                    {
                        OnLogExecuting = (sql, p) =>
                        {
                        }
                    },
                    MoreSettings = new ConnMoreSettings()
                    {
                        IsAutoRemoveDataCache = true
                    },
                    ConfigureExternalServices = new ConfigureExternalServices()
                    {
                        SqlFuncServices = expMethods//set ext method
                    ,DataInfoCacheService = myCache
                    }
                }
               );
            });

            var sugarClient = new SqlSugarScope(listConfig);
            services.AddSingleton<ISqlSugarClient>(sugarClient);//这边是SqlSugarScope用AddSingleton
        }
    }
}